package cn.itcast.wanxinp2p.consumer.service.iml;

import cn.itcast.wanxinp2p.api.account.model.AccountDTO;
import cn.itcast.wanxinp2p.api.account.model.AccountRegisterDTO;
import cn.itcast.wanxinp2p.api.consumer.model.BankCardDTO;
import cn.itcast.wanxinp2p.api.consumer.model.ConsumerDTO;
import cn.itcast.wanxinp2p.api.consumer.model.ConsumerRegisterDTO;
import cn.itcast.wanxinp2p.api.consumer.model.ConsumerRequest;
import cn.itcast.wanxinp2p.api.depository.model.GatewayRequest;
import cn.itcast.wanxinp2p.common.domain.*;
import cn.itcast.wanxinp2p.common.domain.consumer.ConsumerErrorCode;
import cn.itcast.wanxinp2p.common.util.CodeNoUtil;
import cn.itcast.wanxinp2p.consumer.agent.AccountApiAgent;
import cn.itcast.wanxinp2p.consumer.agent.DepositoryAgentApiAgent;
import cn.itcast.wanxinp2p.consumer.entity.BankCard;
import cn.itcast.wanxinp2p.consumer.entity.Consumer;
import cn.itcast.wanxinp2p.consumer.mapper.ConsumerMapper;
import cn.itcast.wanxinp2p.consumer.service.BankCardService;
import cn.itcast.wanxinp2p.consumer.service.ConsumerRegisterTCC;
import cn.itcast.wanxinp2p.consumer.service.ConsumerService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ConsumerServiceImpl extends ServiceImpl<ConsumerMapper, Consumer> implements ConsumerService {

    @Autowired
    private AccountApiAgent accountApiAgent;

    @Autowired
    private ConsumerRegisterTCC consumerRegisterTCC;

    @Autowired
    private BankCardService bankCardService;

    @Autowired
    DepositoryAgentApiAgent depositoryAgentApiAgent;


    @Override
    public Integer checkMobile(String mobile) {
        // 检查用户是否存在 1 存在（老用户）  0 不存在（新用户）
        return getByMobile(mobile) != null ? 1 : 0;
    }

    private ConsumerDTO getByMobile(String mobile) {
        // 根据手机号查询用户信息
        Consumer consumer = getOne(new QueryWrapper<Consumer>().lambda().eq(Consumer::getMobile, mobile));
        return convertConsumerEntityToDTO(consumer);
    }

    @Transactional
    @Override
    public void register(ConsumerRegisterDTO consumerRegisterDTO) {
        // 老用户
        if (checkMobile(consumerRegisterDTO.getMobile()) == 1) {
            throw new BusinessException(ConsumerErrorCode.E_140107);
        }
        // 创建实体consumer
        Consumer consumer = new Consumer();
        // 将前端传递的参数封装到consumer 实体类
        BeanUtils.copyProperties(consumerRegisterDTO, consumer);
        // 给用户自动设置一个编号作为用户名
        consumer.setUsername(CodeNoUtil.getNo(CodePrefixCode.CODE_NO_PREFIX));
        // 将生成后的用户名赋值给 consumerRegisterDTO （后面需要远程调用 account 账户服务）
        consumerRegisterDTO.setUsername(consumer.getUsername());
        // 设置用户编，（用户在存管系统标识）
        consumer.setUserNo(CodeNoUtil.getNo(CodePrefixCode.CODE_REQUEST_PREFIX));
        // 是否绑定银行卡 默认未绑定 0
        consumer.setIsBindCard(0);
        // 保存用户信息
        save(consumer);

        //远程调用account
        AccountRegisterDTO accountRegisterDTO = new AccountRegisterDTO();
        // 将consumerRegisterDTO 转换成 accountRegisterDTO
        BeanUtils.copyProperties(consumerRegisterDTO, accountRegisterDTO);
        // 调用 统一账户微服务 保存用户到 account表
        RestResponse<AccountDTO> restResponse = accountApiAgent.register(accountRegisterDTO);
        // 如果调用失败 抛出BusinessException 提示用户注册失败
        // BusinessException  是运行是异常，因此 事务会回滚。这种方式不是最终解决方案
        if (restResponse.getCode() != CommonErrorCode.SUCCESS.getCode()) {
            throw new BusinessException(ConsumerErrorCode.E_140106);
        }
    }


    // 生成开户数据
    @Override
    public RestResponse<GatewayRequest> createConsumer(ConsumerRequest consumerRequest) {
        //0 . 根据用户传递参数consumerRequest 手机号字段 查询用户信息
        ConsumerDTO consumerDTO = this.getByMobile(consumerRequest.getMobile());
        //1. 判断用户是否已开户 (已经开过户（绑定银行卡状态1）： 已经绑定状态 1  未绑定状态 0 )
        if (consumerDTO.getIsBindCard() == 1) {
            throw new BusinessException(ConsumerErrorCode.E_140105); // 提示用户您已经开过户
        }
        //2. 判断银行卡是否已被绑定
        BankCardDTO bankCardDTO = bankCardService.getByCardNumber(consumerRequest.getCardNumber());
        if (bankCardDTO != null && bankCardDTO.getStatus() == StatusCode.STATUS_IN.getCode()) {
            throw new BusinessException(ConsumerErrorCode.E_140151); // 银行卡已经绑定用户了！（曾经使用一个手机号开过户）
        }
        //3.更新用户开户信息,产生请求流水号和用户编号

        // 3.1 补充完整数据：id
        consumerRequest.setId(consumerDTO.getId());
        // 3.2 补充完善用户编号 （后续存管系统关联字段）
        consumerRequest.setUserNo(CodeNoUtil.getNo(CodePrefixCode.CODE_CONSUMER_PREFIX));
        // 3.3 请求流水编号（后续我们用户每一次交易都会生成一唯一流水编号 ，开户也认为是一次交易）
        consumerRequest.setRequestNo(CodeNoUtil.getNo(CodePrefixCode.CODE_REQUEST_PREFIX));

        //4、设置查询条件和需要更新的数据

        // 4.1 更新用户表数据
      /*
         以下代码全字段修改，所有的字段都修改，没有值 修改null
       LambdaQueryWrapper<Consumer> consumerLambdaQueryWrapper = new LambdaQueryWrapper<>();
        consumerLambdaQueryWrapper.eq(Consumer::getMobile, consumerRequest.getMobile());
        Consumer consumer = new Consumer();
        BeanUtils.copyProperties(consumerRequest,consumer);
        this.update(consumer,consumerLambdaQueryWrapper); // 生成sql 全字段修改 ，针对特定字段修改？？

        */
        // 设置更新条件
        UpdateWrapper<Consumer> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(Consumer::getMobile, consumerRequest.getMobile());  // where mobile =13899998888
        //更新特定字段
        updateWrapper.lambda().set(Consumer::getUserNo, consumerRequest.getRequestNo());
        updateWrapper.lambda().set(Consumer::getFullname, consumerRequest.getFullname());
        updateWrapper.lambda().set(Consumer::getRequestNo, consumerRequest.getRequestNo());
        updateWrapper.lambda().set(Consumer::getIdNumber, consumerRequest.getIdNumber());
        updateWrapper.lambda().set(Consumer::getAuthList, "ALL");
        this.update(updateWrapper); // update consumer set userno=11  .... where mobile =33434

        //4.2 更新银行卡数据
        BankCard bankCard = new BankCard();
        bankCard.setBankCode(consumerRequest.getBankCode());
        bankCard.setConsumerId(consumerDTO.getId());
        bankCard.setCardNumber(consumerRequest.getCardNumber());
        bankCard.setStatus(StatusCode.STATUS_OUT.getCode()); // 银行卡未激活，当开户成功以后再异步方式 更新银行卡状态！！！
        bankCard.setMobile(consumerRequest.getMobile());

        // 根据用户id查询 银行卡表看一下当前用户是否存在银行卡  (p2p 金融业务限定 一个用户手机号只能绑定一个银行账户)
        BankCardDTO cardDTO = bankCardService.getByConsumerId(bankCard.getConsumerId());
        if (cardDTO != null) {
            bankCard.setId(cardDTO.getId());
        }
        //5.保存用户绑卡信息
        bankCardService.saveOrUpdate(bankCard);
        // 6. 调用存管代理服务 （）
        return depositoryAgentApiAgent.createConsumer(consumerRequest);
    }



    /**
     * entity转为dto
     *
     * @param entity
     * @return
     **/
    private ConsumerDTO convertConsumerEntityToDTO(Consumer entity) {
        if (entity == null) {
            return null;
        }
        ConsumerDTO dto = new ConsumerDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

}
